/*
 * openGL.cpp
 *
 *  Created on: 07.10.2011
 *      Author: ignacio
 */
#include "CL_Character.h"
#include "vector.h"
typedef neurignacio::Vector3 Vector;
#include <iostream>
using std::cout;
using std::endl;

namespace neurignacio{

float WindowCoordinateToWorld(const unsigned int& windowCoordinate, const unsigned int& windowSize, const float& worldSize)
// WorldCoordinates=[-worldSize,worldSize)
{
	return windowCoordinate*(2*worldSize-1)/(windowSize-1)-worldSize;
}

unsigned int WorldCoordinateToWindow(const float& worldCoordinate, const unsigned int& windowSize, const float& worldSize)
// WorldCoordinates=[-worldSize,worldSize)
{
	return (worldCoordinate+worldSize)*(windowSize-1)/(2*worldSize-1);
}

void CL_BaseProperties::init(void)
{
	windowSize.x=graphicContext->get_width();
	windowSize.y=graphicContext->get_height();
	if (worldSize==VECTOR_ZERO)
		worldSize=VECTOR_SIZE_GRAPHICCONTEXT;
}

inline Vector CL_BaseProperties::getWindowPosition(const Vector3& position)
{
	Vector windowPosition;
	windowPosition.x=(position.x+worldSize.x)*(windowSize.x-1)/(2*worldSize.x-1);
	windowPosition.y=(-position.z+worldSize.y)*(windowSize.y-1)/(2*worldSize.y-1); // position.z has to be inverted (-1)
	return windowPosition;
}

void CL_Character::bringBackToWorld()
{
	if (!isInsideWorld())
	{
		//Vector worldCenter=windowSize/2;
		position=Vector(0,0,0);
	}

}

void CL_SpriteProperties::draw(const Vector3& position, const bool VERBOSITY)
{
// Orientation according to Clanlib => CLOCKWISE!!!!!
//			UP
//			 0°
//		315° |	45°
//		  \	 |	 /
//		   \ |  /
//	270°––––––––––– 90°
//		   / |  \
//		  /  |   \
//		225° |	 120°
//			180°
//			DOWN
//
//
//				negative
//					^
//					|
//	negative <------+------> positive
//					|
//				positive
// up-down Axis is inverted!!!!

	// position referes to the center of the character, whereas in CL_Sprite to the upper left corner
//	cout << "CL_Properties::draw()!!!!"<<endl;
	Vector dim;
	dim.x=get_height();
	dim.y=get_width();
	Vector scale;
	get_scale(scale.x, scale.y);
	Vector windowPosition = getWindowPosition(position);
//	cout << "\tLine: " << __LINE__ << endl;
	if (VERBOSITY) cout << windowPosition;
//	cout << "dim"<<dim;
//	cout << "scale" << scale;
	Vector posWindow;
	posWindow.x=windowPosition.x-dim.x*scale.x/2;
	posWindow.y=windowPosition.y-dim.y*scale.y/2;
//	cout << "pos"<<posWindow << endl;
//	cout << "\tLine: " << __LINE__ << endl;
	CL_Sprite::draw(*graphicContext, posWindow.x, posWindow.y);
}

void CL_CharacterParent::drawChildren(const bool VERBOSITY)
{
	for (CL_CharacterPointerContainer::iterator child=children->begin();child!=children->end(); ++child)
	{
		if ((*child)!=parent)
				(**child).draw(VERBOSITY);
	}
}

void CL_CharacterParent::draw(const bool VERBOSITY)
{
//	cout << "CL_Character::draw!" << endl;
	if (parentVisibility)
	{
//		cout << "\tdraw parent!!!" << endl;
		parent->draw(VERBOSITY);
	}
	drawChildren(VERBOSITY);
}

bool CL_CharacterParent::isChildrenInsideWorld()
{
	bool answer = true;
	for (CL_CharacterPointerContainer::iterator child=children->begin();child!=children->end(); ++child)
	{
		if ((*child)!=parent)
				answer = (answer && (**child).isInsideWorld());
	}
	return answer;
}

void CL_CharacterParent::bringChildrenBackToWorld()
{
	for (CL_CharacterPointerContainer::iterator child=children->begin();child!=children->end(); ++child)
	{
		if ((*child)!=parent)
				(**child).bringBackToWorld();
	}
}

inline Vector CL_Path::getWindowPosition(const Vector3& position)	// same as CL_Properties
{
	Vector windowPosition;
	windowPosition.x=(int)(position.x+worldSize.x)*(windowSize.x-1)/(2*worldSize.x-1);
	windowPosition.y=(int)(-position.z+worldSize.y)*(windowSize.y-1)/(2*worldSize.y-1); // position.z has to be inverted (-1)
	return windowPosition;
}

void CL_Path::draw(void)
{
	Vector P0;
//	Vector P1(getWindowPosition(this->front()) );
	Vector P1(this->front());
//	cout << *this << endl;
	for (VectorPath::const_iterator point=this->begin()+1; point!=this->end(); ++point)
	{
		P0=P1;
		//P1=getWindowPosition(*(point));
		P1=*point;
		cout << "Drawing Line: " << P0 << "->" << P1 << endl;

		CL_Draw::line(*graphicContext, P0.x, P0.y, P1.x, P1.y, color);
	}
}

/*
LeptonPointerContainer& cast(CL_CharacterPointerContainer source)
{
	LeptonPointerContainer destination;
	for (BasePointerContainer<CL_Character>::iterator it=source.begin(); it!=source.end(); ++it)
		destination.push_back(*it);
	return destination;
}
*/
} // end namespace neurignacio

